<?php

require_once 'PipesImpl/Model.php';
require_once 'PipesImpl/Model/Meta.php';
require_once 'Pipes/Form/Container.php';
require_once 'Pipes/Form/Element.php';
require_once 'Pipes/Form/Controls.php';
require_once 'Pipes/Xml/Document.php';
require_once 'Pipes/Xml/Renderer.php';
require_once 'Pipes/Xml/Xpath.php';

class Pipes_Form_Factory
{
	private $_form = null;
	private $_model = null;
	private $_capture = null;

	public function __construct(PipesImpl_Model $model, $action = null) {
		$this->_model = $model;
		$this->_form = new Pipes_Form_Container();
		if (!is_null($action)) {
			$this->action($action);
		}

		ob_start();
	}

	public function action($uri) {
		$this->_form->action($uri);
	}

	public function doAjax($custom = null) {
		$this->_form->setAttribute('onsubmit', "return Pipes.ajaxify(this){$custom}.process()");
	}
	
	public function render() {
		$string = ob_get_clean();
		if (!empty($string)) {
			$this->_capture = new Pipes_Xml_Document();
			$xml = '<div xmlns:pipes="http://phpinpipes.org/schema/v1">' . $string . '</div>';
			$this->_capture->loadXML($xml);
		}

		$propertyNames = array_merge(
			array_keys($this->_model->getColumns()),
			$this->_model->listRelationships()
		);

		foreach ($propertyNames as $propertyName) {
			if (!is_null($this->_capture)) {
				$xpath = new Pipes_Xml_Xpath($this->_capture);
				$query = "//*[@pipes:for='{$propertyName}']";
				$element = $xpath->query($query);
				if ($element->length > 0) {
					$document = new Pipes_Xml_Document;
					$input = $document->importNode($element->item(0), true);
					$document->appendChild($input);
					
					$renderable = new Pipes_Xml_Renderer($document);
					$this->_form->add($renderable);

					

					// break out of this as we've done our job
					continue;
				}
			}
			
			// skip if its a relationship and custom code isn't specified
			if (in_array($propertyName, $this->_model->listRelationships())) {
				continue;
			}
			$this->_form->add(new Pipes_Form_Element($this->_model, $propertyName));
		}
		
		$this->_form->add(new Pipes_Form_Controls($this->_model));
		
		return $this->_form->render();
	}
}
